package com.yunwaikeji.gy_tool_library.utils;

import android.app.Activity;
import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.widget.EditText;
import android.widget.ScrollView;

import androidx.core.widget.NestedScrollView;

import com.yunwaikeji.gy_tool_library.widget.GYEditText;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 键盘弹出和收回，view显示工具
 * 郭杨
 * 2020/10/15
 */
public class GYKeyboardUpViewUtils {
    private Context context;

    public GYKeyboardUpViewUtils(Context context) {
        this.context = context;
    }

    public static GYKeyboardUpViewUtils getInstance(Context context) {
        return new GYKeyboardUpViewUtils(context);
    }

//    private static class KeyboardUpViewUtilHolder {
//        private static final KeyboardUpViewUtil keyboardUpViewUtil = new KeyboardUpViewUtil();
//    }

    private List<UpViewOfEditTextBean> upViewOfEditTextBeanList = new ArrayList<>();

    private View upView;

    /**
     * 设置弹出键盘永远在键盘上方的view
     *
     * @param upView
     * @return
     */
    public GYKeyboardUpViewUtils addUpView(View upView) {
        this.upView = upView;
        return this;
    }

    /**
     * 设置当前页下获取焦点的EditText在键盘上方
     *
     * @return
     */
    public GYKeyboardUpViewUtils setFocusedEditTextUp() {
        addFocusedEditTextUp(GYUtils.scanForActivity(context).getWindow().getDecorView());
        return this;
    }

    /**
     * 添加指定view下获取焦点的EditText在键盘上方
     *
     * @return
     */
    public GYKeyboardUpViewUtils addFocusedEditTextUp(View... views) {
        addFocusedEditTextUp(Arrays.asList(views));
        return this;
    }

    public GYKeyboardUpViewUtils addFocusedEditTextUp(List<View> viewList) {
        for (View view : viewList) {
            if (view instanceof GYEditText) {
                addUpEditTexts((GYEditText) view);
            } else if (view instanceof ViewGroup) {
                ViewGroup viewGroup = (ViewGroup) view;
                for (int i = 0; i < viewGroup.getChildCount(); i++) {
                    addFocusedEditTextUp(viewGroup.getChildAt(i));
                }
            }
        }
        return this;
    }

    /**
     * 添加在键盘上方的EditText
     *
     * @param editTextList
     * @return
     */
    public GYKeyboardUpViewUtils addUpEditTexts(List<GYEditText> editTextList) {
        for (GYEditText editText : editTextList) {
            addUpViewOfEditTexts(editText, editText);
        }
        return this;
    }

    public GYKeyboardUpViewUtils addUpEditTexts(GYEditText... editTexts) {
        addUpEditTexts(Arrays.asList(editTexts));
        return this;
    }

    /**
     * 添加editText获取焦点，指定的view在键盘上方
     *
     * @param upView
     * @param editTextList
     * @return
     */
    public GYKeyboardUpViewUtils addUpViewOfEditTexts(View upView, List<GYEditText> editTextList) {
        UpViewOfEditTextBean upViewOfEditTextBean = new UpViewOfEditTextBean();
        upViewOfEditTextBean.setUpView(upView);
        upViewOfEditTextBean.setEditTextList(editTextList);
        upViewOfEditTextBeanList.add(upViewOfEditTextBean);
        return this;
    }

    public GYKeyboardUpViewUtils addUpViewOfEditTexts(View upView, GYEditText... editTexts) {
        addUpViewOfEditTexts(upView, Arrays.asList(editTexts));
        return this;
    }

    public void build() {
        Activity activity = GYUtils.scanForActivity(context);
        View view = activity.getWindow().getDecorView();
        view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (upView != null) {
                    setKeyboardUp(activity, view, upView);
                } else {
                    for (UpViewOfEditTextBean upViewOfEditTextBean : upViewOfEditTextBeanList) {
                        boolean isBreak = false;
                        for (GYEditText editText : upViewOfEditTextBean.getEditTextList()) {
                            if (editText.isFocused()) {
                                setKeyboardUp(activity, view, upViewOfEditTextBean.getUpView());
                                isBreak = true;
                                break;
                            }
                        }
                        if (isBreak) {
                            break;
                        } else {
                            setKeyboardUp(activity, view, null);
                        }
                    }
                }
            }
        });
        for (UpViewOfEditTextBean upViewOfEditTextBean : upViewOfEditTextBeanList) {
            for (GYEditText editText : upViewOfEditTextBean.getEditTextList()) {
                editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                    @Override
                    public void onFocusChange(View v, boolean hasFocus) {
                        if (!hasFocus) {
                            GYKeyboardUtils.getInstance().hideSoftInput(context);
                        }
                    }
                });
            }
        }
    }

    public void setKeyboardUp(Context context, View view, View focusView) {
        Rect rect = new Rect();
        view.getWindowVisibleDisplayFrame(rect);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                //获取键盘高度
                int height = view.getHeight() - rect.bottom;
                if (height == 0 || focusView == null) {
                    int scrollY = view.getScrollY();
                    if (scrollY > 0) {
                        view.scrollTo(0, 0);
                    }
                } else {
                    int y = GYUtils.getLocationScreenY(focusView);
                    int windowHeight = GYUtils.getWindowHeight(GYUtils.scanForActivity(context));
                    int viewBottomHeight = windowHeight - y - focusView.getHeight();
                    if (height > viewBottomHeight) {
                        int toScrollY = height - viewBottomHeight;
                        View scrollView = scrollView1(focusView);
                        if (scrollView == null) {
                            view.scrollTo(0, toScrollY);
                        } else {
                            scrollView.scrollBy(0, toScrollY);
                        }
                    }
                }
            }
        }, 200);
    }

    private View scrollView1(View view) {
        ViewParent viewParent = view.getParent();
        if (viewParent != null) {
            View view1 = (View) viewParent;
            if (view1 instanceof ScrollView || view1 instanceof NestedScrollView) {
                return view1;
            } else {
                return scrollView1(view1);
            }
        }
        return null;
    }

    private boolean isFocus = false;

    private boolean isFocusView(View view) {
        isFocus = false;
        if (view instanceof ScrollView || view instanceof NestedScrollView) {
            hasFocusView(view);
        }
        return isFocus;
    }

    private void hasFocusView(View view) {
        if (view instanceof EditText) {
            EditText editText = (EditText) view;
            if (editText.isFocused()) {
                isFocus = true;
            }
        } else if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                hasFocusView(viewGroup.getChildAt(i));
            }
        }
    }

    private Handler handler = new Handler();

    private class UpViewOfEditTextBean {
        private View upView;
        private List<GYEditText> editTextList;

        public View getUpView() {
            return upView;
        }

        public void setUpView(View upView) {
            this.upView = upView;
        }

        public List<GYEditText> getEditTextList() {
            return editTextList;
        }

        public void setEditTextList(List<GYEditText> editTextList) {
            this.editTextList = editTextList;
        }
    }
}